package com.thwj.project.app.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.thwj.common.exception.ServiceException;
import com.thwj.common.utils.WzDateUtil;
import com.thwj.framework.security.LoginUser;
import com.thwj.project.app.api.param.UserDiDiParam;
import com.thwj.project.app.api.vo.MessageTypeVo;
import com.thwj.project.app.api.vo.MessageVo;
import com.thwj.project.app.api.vo.UserDiDiVo;
import com.thwj.project.app.event.UserMessageEvent;
import com.thwj.project.app.event.UserMessageReadEvent;
import com.thwj.project.biz.domain.UserDd;
import com.thwj.project.biz.domain.UserMessage;
import com.thwj.project.biz.enums.AuditStatusEnum;
import com.thwj.project.biz.enums.MessageBelongTypeEnum;
import com.thwj.project.biz.enums.MessageTypeEnum;
import com.thwj.project.biz.service.IUserDdService;
import com.thwj.project.biz.service.IUserMessageService;
import com.thwj.project.biz.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Transactional
@Service
public class AppMessageService {

    @Autowired
    IUserMessageService userMessageService;
    @Autowired
    IUserDdService userDdService;
    @Autowired
    UserInfoResolver userInfoResolver;
    @Autowired
    UserVipResolver userVipResolver;
    @Autowired
    ApplicationEventPublisher applicationEventPublisher;
    @Autowired
    IUserService userService;

    public Page<MessageVo> getMessagePage(Page page, Integer messageType, LoginUser loginUser) {
        Page<UserMessage> userMessagePage = userMessageService.page(page,
                new QueryWrapper<UserMessage>()
                        .eq("user_id", loginUser.getUserId())
                        .eq("message_belong_type", messageType)
                        .orderByDesc("create_date")
        );
        List<MessageVo> messageVoList = new ArrayList<>();
        // 遍历构造数据返回
        for (UserMessage record : userMessagePage.getRecords()) {
            MessageVo messageVo = new MessageVo();
            messageVo.setId(record.getId());
            messageVo.setMessageType(record.getMessageType());

            messageVo.setMessageTitle(record.getMessageTitle());
            messageVo.setMessageContent(record.getMessageContent());
            messageVo.setUserId(record.getSendUserId());

            messageVo.setObjectId(record.getObjectId());
            messageVo.setObjectContent(record.getObjectContent());
            messageVo.setObjectPic(record.getObjectPic());

            messageVo.setMessageDate(WzDateUtil.getShortTime(record.getCreateDate()));

            MessageTypeEnum messageTypeEnum = MessageTypeEnum.getEnumByValue(record.getMessageType());
            if (messageTypeEnum != null) {
                messageVo.setActionType(messageTypeEnum.getActionTypeEnum() == null ? null : messageTypeEnum.getActionTypeEnum().getValue());
                messageVo.setPathLink(MessageTypeEnum.getPath(messageTypeEnum,record.getObjectId()));
            }

            messageVoList.add(messageVo);
        }
        if(!CollectionUtils.isEmpty(userMessagePage.getRecords())) {
            List<Long> messageIdList = userMessagePage.getRecords().stream().map(UserMessage::getId).collect(Collectors.toList());
            // 处理消息已读事件
            applicationEventPublisher.publishEvent(UserMessageReadEvent.builder()
                    .userId(loginUser.getUserId())
                    .messageIdList(messageIdList).build()
            );
        }
        page.setRecords(messageVoList);

        // 用户信息刷新
        userInfoResolver.resolve(messageVoList,MessageVo::getUserId,((obj, nickName, headPic) -> {
            obj.setUserNickName(nickName);
            obj.setUserHeadPic(headPic);
        }));
        // 用户会员刷新
        userVipResolver.resolve(messageVoList, MessageVo::getUserId,((obj,vipOrNot)->{
            obj.setVipOrNot(vipOrNot);
        }));
        return page;
    }

    public List<MessageTypeVo> getMessageTypeList(LoginUser loginUser) {
        //读取用户未读消息
        List<UserMessage> messageList = userMessageService.list(
                new QueryWrapper<UserMessage>()
                        .eq("user_id", loginUser.getUserId())
                        .eq("has_read", false)
        );
        // 固定三个
        List<MessageTypeVo> messageTypeVoList = new ArrayList<>();
        MessageTypeVo messageTypeVo1 = new MessageTypeVo();
        messageTypeVo1.setMessageType(MessageBelongTypeEnum.SYSTEM_MESSAGE.getValue());
        messageTypeVo1.setMessageContent("点击查看最近系统消息");
        messageTypeVo1.setMessageTypePic(MessageBelongTypeEnum.SYSTEM_MESSAGE.getIcon());
        messageTypeVoList.add(messageTypeVo1);
        Long unReadCount1 = messageList.stream().filter(item->item.getMessageBelongType().compareTo(MessageBelongTypeEnum.SYSTEM_MESSAGE.getValue()) ==0).count();
        if(unReadCount1 > 0) {
            messageTypeVo1.setMessageContent("点击查看"+ unReadCount1+" 条未读系统消息");
        }
        messageTypeVo1.setUnReadCount(unReadCount1.intValue());

        MessageTypeVo messageTypeVo2 = new MessageTypeVo();
        messageTypeVo2.setMessageType(MessageBelongTypeEnum.DYNAMICS_MESSAGE.getValue());
        messageTypeVo2.setMessageContent("点击查看最近动态消息");
        messageTypeVo2.setMessageTypePic(MessageBelongTypeEnum.DYNAMICS_MESSAGE.getIcon());
        messageTypeVoList.add(messageTypeVo2);
        Long unReadCount2 = messageList.stream().filter(item->item.getMessageBelongType().compareTo(MessageBelongTypeEnum.DYNAMICS_MESSAGE.getValue()) ==0).count();
        if(unReadCount2 > 0) {
            messageTypeVo2.setMessageContent("点击查看"+ unReadCount2+" 条未读动态消息");
        }
        messageTypeVo2.setUnReadCount(unReadCount2.intValue());

        MessageTypeVo messageTypeVo3 = new MessageTypeVo();
        messageTypeVo3.setMessageType(MessageBelongTypeEnum.DIDI_MESSAGE.getValue());
        messageTypeVo3.setMessageContent("点击查看滴滴新消息");
        messageTypeVo3.setMessageTypePic(MessageBelongTypeEnum.DIDI_MESSAGE.getIcon());
        messageTypeVoList.add(messageTypeVo3);

        Long count = userDdService.count(
                new QueryWrapper<UserDd>()
                .eq("received_user_id", loginUser.getUserId())
                .eq("status", AuditStatusEnum.auditing.getValue()));

        messageTypeVo3.setUnReadCount(count.intValue());

        if(count > 0) {
            messageTypeVo3.setMessageContent("点击查看"+ count +" 条未处理的滴滴消息");
        }

        return messageTypeVoList;
    }



    @Async
    @EventListener
    public void addUserMessage(UserMessageEvent messageEvent){

        UserMessage insert = new UserMessage();

        insert.setCreateDate(new Date());
        insert.setHasRead(false);

        insert.setMessageType(messageEvent.getMessageTypeEnum().getValue());
        insert.setMessageBelongType(messageEvent.getMessageBelongTypeEnum().getValue());

        insert.setUserId(messageEvent.getUserId());
        insert.setMessageUnique(messageEvent.getUnique());

        insert.setMessageTitle(messageEvent.getMessageTitle());
        insert.setMessageContent(messageEvent.getMessageContent());

        insert.setObjectId(messageEvent.getObjectId());
        insert.setObjectPic(messageEvent.getObjectPic());
        insert.setObjectContent(messageEvent.getObjectContent());
        insert.setSendUserId(messageEvent.getSendUserId());

        try {
            userMessageService.save(insert);
        }catch (DuplicateKeyException e){
            log.info("用户消息入库发现记录已存在addUserMessage {}", messageEvent);
        }
    }


    public Page<UserDiDiVo> getUserDiDiVoPage(Page page, LoginUser loginUser) {

        Page<UserDd> userDdPage = userDdService.page(
                page, new QueryWrapper<UserDd>()
                        .eq("send_user_id",loginUser.getUserId()).or()
                        .eq("received_user_id",loginUser.getUserId())
                        .orderByDesc("create_date")
        );
        // 用户didi数据
        List<UserDiDiVo> userDiDiVoList = new ArrayList<>();
        userDdPage.getRecords().forEach(item->{
            UserDiDiVo userDiDiVo = convertUserDiDiVo(item, loginUser.getUserId());
            userDiDiVoList.add(userDiDiVo);
            //如果状态是同意这里需要添加双方的手机号
//            if(AuditStatusEnum.auditing_success.getValue() == item.getStatus()) {
//
//            }
        });
        // 更新用户接受者 获取实时用户头像
        userInfoResolver.resolve(userDiDiVoList,UserDiDiVo::getReceivedUserId,((obj, nickName, headPic, gender, signature, phone, wechat) -> {
            obj.setReceivedUserNickName(nickName);
            obj.setReceivedUserHeadPic(headPic);
            obj.setReceivedUserPhone(phone);
        }));
        // 更新用户发送者 获取实时用户头像
        userInfoResolver.resolve(userDiDiVoList,UserDiDiVo::getSendUserId,((obj, nickName, headPic, gender, signature, phone, wechat) -> {
            obj.setSendUserNickName(nickName);
            obj.setSendUserHeadPic(headPic);
            obj.setSendUserPhone(phone);
        }));
        // 会员刷新
        userVipResolver.resolve(userDiDiVoList, UserDiDiVo::getReceivedUserId,((obj,vipOrNot)->{
            obj.setReceivedUserVipOrNot(vipOrNot);
        }));
        userVipResolver.resolve(userDiDiVoList, UserDiDiVo::getSendUserId,((obj,vipOrNot)->{
            obj.setSendUserVipOrNot(vipOrNot);
        }));
        page.setRecords(userDiDiVoList);

        return page;
    }

    private UserDiDiVo convertUserDiDiVo(UserDd userDd, Long userId) {
        UserDiDiVo userDiDiVo = new UserDiDiVo();
        userDiDiVo.setId(userDd.getId());
        userDiDiVo.setSendUserId(userDd.getSendUserId());
        userDiDiVo.setReceivedUserId(userDd.getReceivedUserId());
        userDiDiVo.setStatus(userDd.getStatus());
        // 当前登录人为 发送人
        if (userDd.getSendUserId().compareTo(userId) == 0) {
            userDiDiVo.setUserRole(1);
        }
        // 当前登录人为 接收人
        if (userDd.getReceivedUserId().compareTo(userId) == 0) {
            userDiDiVo.setUserRole(2);
        }

        userDiDiVo.setCreateDate(WzDateUtil.getShortTime(userDd.getCreateDate()));

        return userDiDiVo;
    }


    public void commitUserDiDi(UserDiDiParam userDiDiParam, LoginUser loginUser) {
        if(userDiDiParam.getUserId().compareTo(loginUser.getUserId()) == 0) {
            throw new ServiceException("本人无需获取联系方式");
        }
        // 读取该用户是否存在向该用户的申请
        UserDd userDd = userDdService.getOne(
                new QueryWrapper<UserDd>()
                        .eq("send_user_id", loginUser.getUserId())
                        .eq("received_user_id", userDiDiParam.getUserId()), false);
        if(userDd == null || AuditStatusEnum.auditing.getValue() != userDd.getStatus()) {
            userDd = new UserDd();
            userDd.setSendUserId(loginUser.getUserId());
            userDd.setReceivedUserId(userDiDiParam.getUserId());
            userDd.setStatus(AuditStatusEnum.auditing.getValue());
            userDd.setCreateDate(new Date());
            userDd.setModifyDate(new Date());
            userDdService.save(userDd);
        }
    }

    public void confirmUserDiDi(Long userDiDiId, LoginUser loginUser) {
        UserDd userDd = userDdService.getById(userDiDiId);
        if(userDd == null) {
            throw new ServiceException("记录不存在");
        }
        //
        if(userDd.getReceivedUserId().compareTo(loginUser.getUserId()) != 0) {
            throw new ServiceException("操作失败，只有接受这才能同意");
        }
        if(AuditStatusEnum.auditing.getValue() != userDd.getStatus()) {
            throw new ServiceException("申请已处理，无需重复处理");
        }
        userDd.setStatus(AuditStatusEnum.auditing_success.getValue());
        userDd.setModifyDate(new Date());
        userDdService.updateById(userDd);
    }

    public void refuseUserDiDi(Long userDiDiId, LoginUser loginUser) {
        UserDd userDd = userDdService.getById(userDiDiId);
        if(userDd == null) {
            throw new ServiceException("记录不存在");
        }
        if(userDd.getReceivedUserId().compareTo(loginUser.getUserId()) != 0) {
            throw new ServiceException("操作失败，只有接受这才能同意");
        }
        if(AuditStatusEnum.auditing.getValue() != userDd.getStatus()) {
            throw new ServiceException("申请已处理，无需重复处理");
        }
        userDd.setStatus(AuditStatusEnum.auditing_fail.getValue());
        userDd.setModifyDate(new Date());
        userDdService.updateById(userDd);
    }

    public Integer getMessageUnReadCount(LoginUser loginUser) {
        //读取用户未读消息
        Long unReadCount = userMessageService.count(
                new QueryWrapper<UserMessage>()
                        .eq("user_id", loginUser.getUserId())
                        .eq("has_read", false)
        );

        Long count = userDdService.count(
                new QueryWrapper<UserDd>()
                        .eq("received_user_id", loginUser.getUserId())
                        .eq("status", AuditStatusEnum.auditing.getValue()));

        return Long.valueOf(unReadCount + count).intValue();
    }
}
